// zobrist.h
#ifndef ZOBRIST_H
#define ZOBRIST_H

#include "gotypes.h"
#include <unordered_map>
#include <random>
#include <cstdint>

class Zobrist {
public:
    Zobrist(int max_row, int max_col) : empty_board(0) {
        std::mt19937_64 rng(std::random_device{}());
        std::uniform_int_distribution<uint64_t> dist(0, MAX63);

        for (int row = 1; row <= max_row; ++row) {
            for (int col = 1; col <= max_col; ++col) {
                Point point(row, col);
                table[{point, Player::Black}] = dist(rng);
                table[{point, Player::White}] = dist(rng);
            }
        }
    }

    uint64_t get_empty_board() const {
        return empty_board;
    }

    uint64_t get_code(const Point& point, Player player) const {
        auto it = table.find({ point, player });
        if (it != table.end()) {
            return it->second;
        }
        return 0;
    }

private:
    static const uint64_t MAX63 = 0x7FFFFFFFFFFFFFFF;
    uint64_t empty_board;
    std::unordered_map<std::pair<Point, Player>, uint64_t, 
        std::hash<std::string>> table;

    // Custom hash for std::pair<Point, Player>
    struct pair_hash {
        std::size_t operator()(const std::pair<Point, Player>& p) const {
            return std::hash<int>()(p.first.row) ^ (std::hash<int>()(p.first.col) << 1) 
                   ^ (std::hash<int>()(static_cast<int>(p.second)) << 2);
        }
    };

public:
    // Adjusted to use the correct hash function
    std::unordered_map<std::pair<Point, Player>, uint64_t, pair_hash> table_correct;

    // Initialize the correct table in constructor
    // (Alternative to above table definition)
};

#endif // ZOBRIST_H
